home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Libraries / 3DGPL 1.0 / CODE / GRAPHICS / GRP-POLY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-08  |  12.4 KB  |  329 lines  |  [TEXT/MACA]

  1. /** 3DGPL *************************************************\
  2.  *  (8bit deep bitmap)                                    *
  3.  *  2D graphics and 2D clipping extentions for shaded     *
  4.  *  and textured polygons (has to be linked with regular  *
  5.  *  routines).                                            *
  6.  *                                                        *
  7.  *  Defines:                                              *
  8.  *   G_ambient_polygon       regular polygon;             *
  9.  *   G_shaded_polygon        shaded polygon;              *
  10.  *   G_textured_polygon      textured polygon.            *
  11.  *                                                        *
  12.  *  Internals:                                            *
  13.  *   GI_scan                 scanning an edge;            *
  14.  *   GI_boarder_array_init   init left/right boundaries.  *
  15.  *                                                        *
  16.  *  (6/1995) By Sergei Savchenko. (savs@cs.mcgill.ca).    *
  17.  *  Copyright (c) 1995 Sergei Savchenko.                  *
  18.  *  THIS SOURCE CODE CAN'T BE USED FOR COMERCIAL PURPOSES *
  19.  *  WITHOUT AUTHORISATION                                 *
  20. \**********************************************************/
  21.  
  22. #include <limits.h>                         /* INT_MAX/INT_MIN */
  23.  
  24. #ifdef __MWERKS__
  25. #include "hardware.h"           /* hardware specific stuff */
  26. #include "clipper.h"             /* 2D clipping */
  27. #include "graphics.h"           /* 2D macros */  
  28. #include "trans.h"                 /* T_LOG_FOCUS */
  29. #else
  30. #include "../hardware/hardware.h"           /* hardware specific stuff */
  31. #include "../clipper/clipper.h"             /* 2D clipping */
  32. #include "../graphics/graphics.h"           /* 2D macros */  
  33. #include "../trans/trans.h"                 /* T_LOG_FOCUS */
  34. #endif
  35.  
  36. extern unsigned char *G_buffer;             /* the bitmap's bits */
  37.  
  38. int G_start[HW_SCREEN_Y_SIZE];              /* polygon's */
  39. int G_end[HW_SCREEN_Y_SIZE];                /* horizontal boundaries */
  40. int G_miny,G_maxy;                          /* vertical boundaries */
  41.  
  42. #define G_P      10                         /* fixed point math prcision */
  43. #define G_LINEAR 32                         /* linearely interpolate for */
  44.  
  45. signed_32_bit G_0_start[HW_SCREEN_Y_SIZE];  /* contains [32-G_P].[G_P] values */
  46. signed_32_bit G_0_end[HW_SCREEN_Y_SIZE];    /* this thingie is to work faster */
  47. signed_32_bit G_1_start[HW_SCREEN_Y_SIZE];  /* then multidimensional array */
  48. signed_32_bit G_1_end[HW_SCREEN_Y_SIZE];    /* hope so, */
  49. signed_32_bit G_2_start[HW_SCREEN_Y_SIZE];
  50. signed_32_bit G_2_end[HW_SCREEN_Y_SIZE];
  51.  
  52. signed_32_bit *G_rest_start[C_MAX_DIMENSIONS]={G_0_start,G_1_start,G_2_start};
  53. signed_32_bit *G_rest_end[C_MAX_DIMENSIONS]={G_0_end,G_1_end,G_2_end};
  54.  
  55. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  56.  *  INTERNAL: Scan converting a N dimensional line.      *
  57.  *  ---------                                            *  
  58. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  59.  
  60. void GI_scan(int *edges,int dimension,int skip)
  61. {
  62.  signed_32_bit cur_v[C_MAX_DIMENSIONS];     /* initial values for Z+ dims */
  63.  signed_32_bit inc_v[C_MAX_DIMENSIONS];     /* increment for Z+ dimensions */
  64.  signed_32_bit tmp;
  65.  int dx,dy,long_d,short_d;
  66.  register int d,add_dh,add_dl;              
  67.  register int inc_xh,inc_yh,inc_xl,inc_yl;  
  68.  int x,y,i,j;
  69.  int *v1,*v2;                               /* first and second vertices */
  70.  
  71.  v1=edges; edges+=skip; v2=edges;           /* length ints in each */
  72.  
  73.  if(C_line_y_clipping(&v1,&v2,dimension))   /* vertical clipping */
  74.  {
  75.   dx=*v2++; dy=*v2++;                       /* extracting 2-D coordinates */
  76.   x=*v1++; y=*v1++;                         /* v2/v1 point remaining dim-2 */
  77.   dimension-=2; 
  78.  
  79.   if(y<G_miny) G_miny=y;
  80.   if(y>G_maxy) G_maxy=y;
  81.   if(dy<G_miny) G_miny=dy;
  82.   if(dy>G_maxy) G_maxy=dy;                  /* updating vertical size */
  83.  
  84.   dx-=x; dy-=y;                             /* ranges */
  85.  
  86.   if(dx<0){dx=-dx; inc_xh=-1; inc_xl=-1;}   /* making sure dx and dy >0 */
  87.   else    {        inc_xh=1;  inc_xl=1; }   /* adjusting increments */
  88.   if(dy<0){dy=-dy; inc_yh=-1; inc_yl=-1;}
  89.   else    {        inc_yh=1;  inc_yl=1; }
  90.  
  91.   if(dx>dy){long_d=dx;short_d=dy;inc_yl=0;} /* long range,&making sure either */
  92.   else     {long_d=dy;short_d=dx;inc_xl=0;} /* x or y is changed in L case */
  93.  
  94.   d=2*short_d-long_d;                       /* initial value of d */
  95.   add_dl=2*short_d;                         /* d adjustment for H case */
  96.   add_dh=2*short_d-2*long_d;                /* d adjustment for L case */
  97.  
  98.   for(i=0;i<dimension;i++)                  /* for all remaining dimensions */
  99.   {
  100.    tmp=v1[i]; tmp<<=G_P; cur_v[i]=tmp;      /* f.p. start value */
  101.    tmp=v2[i]-v1[i]; tmp<<=G_P;              /* f.p. increment */
  102.    if(long_d>0) inc_v[i]=tmp/long_d;        /* if needed (non 0 lines) */
  103.   }
  104.  
  105.   for(i=0;i<=long_d;i++)                    /* for all points in longer range */
  106.   {
  107.    if(x<G_start[y])                         /* further then rightmost */
  108.    {
  109.     G_start[y]=x;                           /* the begining of scan line */
  110.     for(j=0;j<dimension;j++)
  111.      G_rest_start[j][y]=cur_v[j];            /* all other dimensions */
  112.    }
  113.  
  114.    if(G_end[y]<x)                           /* further the leftmost */
  115.    {
  116.     G_end[y]=x;                             /* the end of scan line */
  117.     for(j=0;j<dimension;j++)
  118.      G_rest_end[j][y]=cur_v[j];              /* and for other dimension */
  119.    }
  120.  
  121.    if(d>=0){x+=inc_xh;y+=inc_yh;d+=add_dh;} /* previous point was H type */
  122.    else    {x+=inc_xl;y+=inc_yl;d+=add_dl;} /* previous point was L type */
  123.    for(j=0;j<dimension;j++) 
  124.     cur_v[j]+=inc_v[j];                     /* for all other dimensions */
  125.   }
  126.  }
  127. }
  128.  
  129. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
  130.  *  INTERNAL: Initialization of polygon boundaries.      *
  131.  *  ---------                                            *
  132. \* * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  133.  
  134. void GI_boarder_array_init(void)
  135. {
  136.  G_miny=INT_MAX;                            /* polygon starts here */
  137.  G_maxy=INT_MIN;                            /* polygon ends here */
  138.  
  139.  HW_set_int(G_start,HW_SCREEN_Y_SIZE,INT_MAX);
  140.  HW_set_int(G_end,HW_SCREEN_Y_SIZE,INT_MIN);/* limiting values */
  141. }
  142.  
  143. /**********************************************************\
  144.  *  Rendering a polygon.                                  *
  145.  *  Accepts 2-tuples (X,Y) per vertex.                    *
  146. \**********************************************************/
  147.  
  148. void G_ambient_polygon(int *edges,int length,unsigned char colour)
  149. {
  150.  int new_edges[G_MAX_TUPLES];               /* verticaly clipped polygon */
  151.  int new_length;                            /* although no edges there yet */
  152.  register unsigned char *l_adr,*adr;        
  153.  register int beg,end,i;
  154.  
  155.  GI_boarder_array_init();                   /* initializing the arrays */
  156.  
  157.  new_length=C_polygon_x_clipping(edges,new_edges,2,length);
  158.  
  159.  for(i=0;i<new_length;i++)
  160.   GI_scan(&new_edges[i*2],2,2);             /* Searching polygon boarders */
  161.  
  162.  if(G_miny<=G_maxy)                         /* nothing to do? */
  163.  {
  164.   l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE;   /* addr of 1st byte of 1st line */
  165.  
  166.   for(; G_miny<=G_maxy; G_miny++,
  167.       l_adr+=HW_SCREEN_X_SIZE)              /* rendering all lines */
  168.   {
  169.    adr=l_adr+(beg=G_start[G_miny]);         /* addr of the current line */
  170.    end=G_end[G_miny]-beg+1;                 /* ends here */
  171.  
  172.    HW_set_char((char*)adr,end,colour);      /* rendering single line */
  173.   }
  174.  }
  175. }
  176.  
  177. /**********************************************************\
  178.  *  Rendering an Interpolatively shaded polygon.          *
  179.  *  Accepts 3-tuples (X,Y,ColourIntensity) per vertex.    *
  180. \**********************************************************/
  181.  
  182. void G_shaded_polygon(int *edges,int length)
  183. {
  184.  int new_edges[G_MAX_SHADED_TUPLES];        /* verticaly clipped polygon */
  185.  int new_length;
  186.  register unsigned char *l_adr,*adr;        
  187.  register int beg,end,i;
  188.  register signed_32_bit cur_c,inc_c;        /* current colour and it's inc */
  189.  
  190.  GI_boarder_array_init();                   /* initializing the array */
  191.  
  192.  new_length=C_polygon_x_clipping(edges,new_edges,3,length);
  193.  
  194.  for(i=0;i<new_length;i++)
  195.   GI_scan(&new_edges[i*3],3,3);             /* Searching polygon boarders */
  196.  
  197.  if(G_miny<=G_maxy)                         /* nothing to do? */
  198.  {
  199.   l_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE;   /* addr of 1st byte of 1st line */
  200.  
  201.   for(; G_miny<=G_maxy; G_miny++,
  202.       l_adr+=HW_SCREEN_X_SIZE)              /* rendering all lines */
  203.   {
  204.    adr=l_adr+(beg=G_start[G_miny]);         /* addr of the current line */
  205.    end=G_end[G_miny];                       /* ends here */
  206.  
  207.    cur_c=G_0_start[G_miny];                 /* colour starts with this value */
  208.    inc_c=G_0_end[G_miny]-cur_c;
  209.    if(end>beg) inc_c/=end-beg+1;            /* f.p. increment */
  210.  
  211.    for(;beg<=end;beg++)                     /* render this lines */
  212.    {
  213.     *adr++=cur_c>>G_P;                      /* rendering single point */
  214.     cur_c+=inc_c;                           /* incrementing colour */
  215.    }
  216.   }
  217.  }
  218. }
  219.  
  220. /**********************************************************\
  221.  *  Rendering a texture rendered polygon.                 *
  222.  *  Accepts 4-tuples - (X,Y,TextureX,TextureY) per vertex.*
  223.  *  The applied texture is a 8bit deep square bitmap with:*
  224.  *                                                        *
  225.  *              log_texture_size=log texture_size         *
  226.  *                                  2                     *
  227. \**********************************************************/
  228.  
  229. void G_textured_polygon(int *edges,int length,int *O,int *u,int *v,
  230.             unsigned char *texture,int log_texture_size,
  231.                            int log_texture_scale
  232.                )
  233. {
  234.  int new_edges[G_MAX_SHADED_TUPLES];        /* verticaly clipped polygon */
  235.  int new_length;
  236.  signed_32_bit Vx,Vy,Vz;
  237.  signed_32_bit Ux,Uy,Uz;                    /* extracting vectors */
  238.  signed_32_bit x0,y0,z0;
  239.  signed_32_bit ui,uj,uc;
  240.  signed_32_bit vi,vj,vc;
  241.  signed_32_bit zi,zj,zc;                    /* back to texture coeficients */
  242.  signed_32_bit v0,u0;
  243.  signed_32_bit xx,yy,zz,zzz;                
  244.  int xstart,xend;
  245.  signed_32_bit txstart,tystart;
  246.  signed_32_bit txend,tyend;
  247.  signed_32_bit txinc,tyinc;
  248.  register unsigned char *g_adr,*adr;        
  249.  register int i,x,y;
  250.  signed_32_bit txtrmasc=(0x1<<(log_texture_size+G_P))-0x1;
  251.  log_texture_scale+=G_P;
  252.  
  253.  GI_boarder_array_init();                   /* initializing the array */
  254.  
  255.  new_length=C_polygon_x_clipping(edges,new_edges,4,length);
  256.  
  257.  for(i=0;i<new_length;i++)
  258.   GI_scan(&new_edges[i*4],2,4);             /* Searching polygon boarders */
  259.  
  260.  if(G_miny<=G_maxy)                         /* nothing to do? */
  261.  {
  262.   x0=O[0]; y0=O[1]; z0=O[2]; 
  263.   u0=O[3]<<G_P; v0=O[4]<<G_P;               /* world point <-> texture point */
  264.  
  265.   Vx=v[0]; Vy=v[1]; Vz=v[2];
  266.   Ux=u[0]; Uy=u[1]; Uz=u[2];                /* extracting vectors */
  267.  
  268.   ui=(Vz*y0)-(Vy*z0);
  269.   uj=(Vx*z0)-(Vz*x0);
  270.   uc=(Vy*x0)-(Vx*y0);
  271.   vi=(Uy*z0)-(Uz*y0);
  272.   vj=(Uz*x0)-(Ux*z0);
  273.   vc=(Ux*y0)-(Uy*x0);
  274.   zi=(Vy*Uz)-(Vz*Uy);
  275.   zj=(Vz*Ux)-(Vx*Uz);
  276.   zc=(Vx*Uy)-(Vy*Ux);                       /* back to texture */
  277.  
  278.   g_adr=G_buffer+G_miny*HW_SCREEN_X_SIZE;   /* addr of 1st byte of 1st line */
  279.  
  280.   for(; G_miny<=G_maxy; G_miny++,
  281.       g_adr+=HW_SCREEN_X_SIZE)              /* rendering all lines */
  282.   {
  283.    xstart=G_start[G_miny];
  284.    adr=g_adr+xstart;
  285.    xstart-=HW_SCREEN_X_CENTRE;
  286.    x=xstart;
  287.    xend=G_end[G_miny]-HW_SCREEN_X_CENTRE;   
  288.    y=G_miny-HW_SCREEN_Y_CENTRE;
  289.  
  290.    xx=((y*uj)>>T_LOG_FOCUS)+uc;
  291.    yy=((y*vj)>>T_LOG_FOCUS)+vc;
  292.    zz=((y*zj)>>T_LOG_FOCUS)+zc;             /* valid for the hole run */
  293.  
  294.    if(( zzz=zz+((x*zi)>>T_LOG_FOCUS) )!=0) 
  295.    { 
  296.     txend=( (xx+ ((x*ui)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +u0;
  297.     tyend=( (yy+ ((x*vi)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +v0; 
  298.    }
  299.  
  300.    for(;xstart<xend;)
  301.    {
  302.     x+=G_LINEAR; if(x>xend) x=xend;         /* size of linear run */
  303.     txstart=txend;
  304.     tystart=tyend;
  305.  
  306.     if(( zzz=zz+((x*zi)>>T_LOG_FOCUS) )!=0) 
  307.     { 
  308.      txend=( (xx+ ((x*ui)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +u0;
  309.      tyend=( (yy+ ((x*vi)>>T_LOG_FOCUS)) <<log_texture_scale )/zzz +v0; 
  310.     }
  311.  
  312.     length=x-xstart;                        /* ends here */
  313.     if(length!=0) { txinc=(txend-txstart)/length; 
  314.             tyinc=(tyend-tystart)/length;
  315.           }
  316.  
  317.     for(;xstart<x;xstart++)                 /* linear run */
  318.     {
  319.      txstart&=txtrmasc; tystart&=txtrmasc;  /* wrap around */
  320.      *adr++=*(texture+((tystart>>G_P)<<log_texture_size)+(txstart>>G_P));
  321.      txstart+=txinc; tystart+=tyinc;        /* new position in the texture */
  322.     }
  323.    }
  324.   }
  325.  }
  326. }
  327.  
  328. /**********************************************************/
  329.